home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 52
/
Amiga Format AFCD52 (Issue 136, May 2000).iso
/
-serious-
/
programming
/
other
/
dopus412-gpl
/
program
/
buffers.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-28
|
16KB
|
610 lines
/*
Directory Opus 4
Original GPL release version 4.12
Copyright 1993-2000 Jonathan Potter
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
All users of Directory Opus 4 (including versions distributed
under the GPL) are entitled to upgrade to the latest version of
Directory Opus version 5 at a reduced price. Please see
http://www.gpsoft.com.au for more information.
The release of Directory Opus 4 under the GPL in NO WAY affects
the existing commercial status of Directory Opus 5.
*/
#include "dopus.h"
/* Allocate or free directory buffers as necessary to achieve desired
buffer count in each window */
void allocdirbuffers(newnum)
int newnum;
{
int win,a,num;
struct DirectoryWindow *dir,*next;
for (win=0;win<2;win++) {
if (data_buffer_count[win]>newnum) {
dir=dopus_firstwin[win];
for (a=0;a<newnum;a++) dir=dir->next;
dir->last->next=dopus_firstwin[win];
dopus_firstwin[win]->last=dir->last;
num=data_buffer_count[win];
for (a=newnum;a<num;a++) {
next=dir->next;
freedir(dir,-1);
if (dopus_curwin[win]==dir) dopus_curwin[win]=dopus_firstwin[win];
FreeMem(dir,sizeof(struct DirectoryWindow));
if ((--data_buffer_count[win])<1) break;
dir=next;
}
}
else if (data_buffer_count[win]<newnum) {
dir=dopus_firstwin[win];
for (a=0;a<data_buffer_count[win]-1;a++) dir=dir->next;
for (a=data_buffer_count[win];a<newnum;a++) {
if (next=AllocMem(sizeof(struct DirectoryWindow),MEMF_CLEAR)) {
if (!dir) {
dopus_firstwin[win]=next;
dopus_curwin[win]=next;
dir=next;
}
dir->next=next;
next->last=dir;
next->next=dopus_firstwin[win];
dopus_firstwin[win]->last=next;
next->number=a;
next->hlen=145;
++data_buffer_count[win];
dir=next;
}
}
}
}
}
/* Searches both buffer lists for a given directory, and displays it in
the active window if found (copying it over if necessary) */
bringinbuffer(dirbuf,win,read)
char *dirbuf;
int win,read;
{
int a,otherwin;
struct DirectoryWindow *dir;
if (status_iconified || !dirbuf) return(0);
checkcurrentbuffer(win);
if (!(findbuffer(dirbuf,win,0,0))) {
otherwin=1-data_active_window;
dir=dopus_firstwin[otherwin];
for (a=0;a<data_buffer_count[otherwin];a++,dir=dir->next) {
if ((LStrCmpI(dirbuf,dir->directory))==0) {
incrementbuf(data_active_window,1,0);
copydirwin(dir,dopus_curwin[data_active_window],data_active_window);
check_old_buffer(data_active_window);
return(1);
}
}
if (read) {
strcpy(str_pathbuffer[data_active_window],dirbuf);
startgetdir(data_active_window,SGDFLAGS_CANMOVEEMPTY);
}
else return(0);
}
return(1);
}
/* Searches forward from the current buffer to find an empty one, or one
with the same name (it looks first for one with the same name).
If a buffer is not found, it uses the current buffer */
void findemptybuffer(win)
int win;
{
struct DirectoryWindow *dir;
int a,ok=0;
char fullbuf[256];
expand_path(str_pathbuffer[win],fullbuf);
checkdir(str_pathbuffer[win],NULL);
checkdir(fullbuf,NULL);
dir=dopus_curwin[win];
for (a=0;a<data_buffer_count[win];a++) {
if (LStrCmpI(dir->directory,str_pathbuffer[win])==0 ||
LStrCmpI(dir->directory,fullbuf)==0) {
ok=1;
break;
}
dir=dir->next;
}
if (!ok) {
dir=dopus_curwin[win];
for (a=0;a<data_buffer_count[win];a++) {
if (!dir->directory[0]) break;
dir=dir->next;
}
}
dopus_curwin[win]=dir;
}
/* Sets up and reads a new directory */
void startgetdir(win,flags)
int win,flags;
{
checkcurrentbuffer(win);
if (!(config->dirflags&DIRFLAGS_CHECKBUFS && (flags&SGDFLAGS_CANCHECKBUFS)) ||
!(findbuffer(str_pathbuffer[win],win,1,0))) {
if ((config->dirflags&DIRFLAGS_FINDEMPTY) && (flags&SGDFLAGS_CANMOVEEMPTY))
findemptybuffer(win);
if (str_pathbuffer[win][0]==0) expand_path("",str_pathbuffer[win]);
checkdir(str_pathbuffer[win],&path_strgadget[win]);
strcpy(dopus_curwin[win]->directory,str_pathbuffer[win]);
getdir(dopus_curwin[win],win,(flags&SGDFLAGS_REREADINGOLD));
}
seename(win);
refreshwindow(win,0);
}
/* Moves forward or backward a buffer and refreshes display */
void incrementbuf(win,dir,show)
int win,dir,show;
{
advancebuf(win,dir);
strcpy(str_pathbuffer[win],dopus_curwin[win]->directory);
checkdir(str_pathbuffer[win],&path_strgadget[win]);
checksize(win);
check_old_buffer(win);
if (show) {
seename(win);
refreshwindow(win,1);
doselinfo(win);
}
startnotify(win);
}
/* Copies the contents of one window to another */
void copydirwin(sourcewin,destwin,dest)
struct DirectoryWindow *sourcewin,*destwin;
int dest;
{
struct Directory *copy;
if (status_iconified) return;
busy();
freedir(destwin,dest);
copy=sourcewin->firstentry;
strcpy(destwin->realdevice,sourcewin->realdevice);
while (copy) {
if (!(addfile(destwin,dest,copy->name,copy->size,copy->type,©->date,
copy->comment,copy->protection,copy->subtype,FALSE,copy->dispstr,NULL,
copy->owner_id,copy->group_id))) break;
copy=copy->next;
}
strcpy(str_pathbuffer[dest],sourcewin->directory);
strcpy(destwin->directory,sourcewin->directory);
strcpy(destwin->diskname,sourcewin->diskname);
destwin->hlen=sourcewin->hlen;
destwin->flags=sourcewin->flags;
copy_datestamp(&sourcewin->dirstamp,&destwin->dirstamp);
refreshwindow(dest,1);
checkdir(str_pathbuffer[dest],&path_strgadget[dest]);
checksize(dest);
last_selected_entry=NULL;
okay();
unbusy();
}
/* Swaps the contents of the two windows */
void swapdirwin()
{
int tmp;
struct DirectoryWindow tempwin;
if (status_iconified) return;
CopyMem((char *)dopus_curwin[0],(char *)&tempwin,sizeof(struct DirectoryWindow));
tempwin.next=dopus_curwin[1]->next; tempwin.number=dopus_curwin[1]->number;
tempwin.last=dopus_curwin[1]->last;
dopus_curwin[1]->next=dopus_curwin[0]->next; dopus_curwin[1]->number=dopus_curwin[0]->number;
dopus_curwin[1]->last=dopus_curwin[0]->last;
CopyMem((char *)dopus_curwin[1],(char *)dopus_curwin[0],sizeof(struct DirectoryWindow));
CopyMem((char *)&tempwin,(char *)dopus_curwin[1],sizeof(struct DirectoryWindow));
for (tmp=0;tmp<2;tmp++) {
strcpy(str_pathbuffer[tmp],dopus_curwin[tmp]->directory);
refreshwindow(tmp,1);
checkdir(str_pathbuffer[tmp],&path_strgadget[tmp]);
checksize(tmp);
}
okay();
}
/* Moves forwards or backwards a directory */
void advancebuf(win,dir)
int win,dir;
{
int a;
endnotify(win);
if (!checkcurrentbuffer(win)) {
if (dir>0) {
for (a=0;a<dir;a++) dopus_curwin[win]=dopus_curwin[win]->next;
}
else {
for (a=dir;a<0;a++) dopus_curwin[win]=dopus_curwin[win]->last;
}
}
}
/* Clears the contents of all unshown buffers */
void clearbuffers()
{
int a,win;
struct DirectoryWindow *dir;
busy();
for (win=0;win<2;win++) {
dir=dopus_firstwin[win];
for (a=0;a<data_buffer_count[win];a++) {
if (dopus_curwin[win]!=dir) {
freedir(dir,-1);
dir->directory[0]=0;
}
dir=dir->next;
}
}
unbusy();
dostatustext(globstring[STR_BUFFERS_CLEARED]);
}
/* Searches backwards for a named buffer and moves to it if found */
struct DirectoryWindow *findbuffer(dirbuf,win,canchecklocks,onlyreturn)
char *dirbuf;
int win,canchecklocks,onlyreturn;
{
int a,founddir=0,ret=0,try,checklocks=0;
struct DirectoryWindow *dir;
BPTR lock=0,testlock;
struct FileInfoBlock __aligned fblock;
char tempbuf[300];
if (status_iconified) return(NULL);
dir=dopus_curwin[win];
main_proc->pr_WindowPtr=(APTR)-1;
strcpy(tempbuf,dirbuf);
if (config->dirflags&DIRFLAGS_EXPANDPATHS) {
canchecklocks=0;
expand_path(dirbuf,tempbuf);
}
TackOn(tempbuf,NULL,300);
for (try=0;try<2;try++) {
if (checklocks && !(lock=Lock(tempbuf,ACCESS_READ))) break;
for (a=0;a<data_buffer_count[win];a++,dir=dir->last) {
if (dir->directory[0]) {
if (checklocks &&
(testlock=Lock(dir->directory,ACCESS_READ))) {
if (CompareLock(lock,testlock)==LOCK_SAME) founddir=1;
UnLock(testlock);
if (!founddir) continue;
}
if (founddir || (LStrCmpI(tempbuf,dir->directory))==0) {
if (!(lockandexamine(tempbuf,&fblock)) ||
(CompareDate(&fblock.fib_Date,&dir->dirstamp)!=0)) continue;
if (!onlyreturn) go_to_buffer(win,dir);
ret=1;
break;
}
}
}
if (ret) break;
if (canchecklocks) checklocks=1;
else break;
}
if (lock) UnLock(lock);
if (config->errorflags&ERROR_ENABLE_DOS) main_proc->pr_WindowPtr=(APTR)Window;
return((ret)?dir:NULL);
}
/* Checks all buffers for a pathname and changes it to the new
pathname if found */
void renamebuffers(old,new)
char *old,*new;
{
int a,win;
struct DirectoryWindow *dir;
for (win=0;win<2;win++) {
dir=dopus_firstwin[win];
for (a=0;a<data_buffer_count[win];a++) {
if (replacepart(dir->directory,old,new) && dopus_curwin[win]==dir) {
strcpy(str_pathbuffer[win],dir->directory);
checkdir(str_pathbuffer[win],&path_strgadget[win]);
}
dir=dir->next;
}
}
}
replacepart(string,old,new)
char *string,*old,*new;
{
int oldlen,stringlen;
char tempbuf[256];
oldlen=strlen(old);
if (LStrnCmpI(string,old,oldlen)) return(0);
if ((stringlen=strlen(string))>oldlen) {
stringlen-=oldlen;
strncpy(tempbuf,&string[oldlen],stringlen);
tempbuf[stringlen]=0;
}
else stringlen=0;
strcpy(string,new);
if (stringlen>0) StrConcat(string,tempbuf,256);
return(1);
}
/* Generates a list of all available buffers in a window */
void dolistbuffers(destwin)
int destwin;
{
int a,b,c,win;
struct DateStamp ds;
struct DirectoryWindow *dir;
char name[2];
if (status_iconified) return;
makespecialdir(destwin,globstring[STR_BUFFER_LIST_TITLE]);
busy(); b=scrdata_dispwin_nchars[destwin]; name[0]=0;
DateStamp(&ds);
for (win=0;win<2;win++) {
dir=dopus_firstwin[win];
for (a=0;a<data_buffer_count[win];a++) {
if (dir->directory[0]) {
addfile(dopus_curwin[destwin],destwin,name,0,
ENTRY_CUSTOM,&ds,dir->directory,0,
CUSTOMENTRY_BUFFERLIST,FALSE,dir->directory,NULL,0,0);
if ((c=strlen(dir->directory))>b) b=c;
}
dir=dir->next;
}
}
dopus_curwin[destwin]->hlen=b;
refreshwindow(destwin,3);
unbusy();
okay();
}
/* Check if buffer is a special buffer, and return to normal if so */
checkcurrentbuffer(win)
int win;
{
if (dopus_curwin[win]==dopus_specialwin[win]) {
dopus_curwin[win]=dopus_oldwin[win];
return(1);
}
return(0);
}
/* Send message to custom entry handler */
void userentrymessage(dir,entry,type)
struct DirectoryWindow *dir;
struct Directory *entry;
int type;
{
struct RexxMsg *msg,*reply;
struct MsgPort *port;
int fail=0;
/* If no customhandler installed or rexx library is not there, return */
if (!dir->custhandler[0] || !RexxSysBase) return;
/* Attempt to create the message packet */
if (!(msg=CreateRexxMsg(general_port,NULL,str_arexx_portname))) fail=1;
else {
/* Set message type (and argument count of 4) */
msg->rm_Action=RXFUNC|4;
/* Fill out argument pointers.
Arg0 = operation type
Arg1 = entry number
Arg2 = entry text
Arg3 = userdata */
msg->rm_Args[0]=(STRPTR)type;
msg->rm_Args[1]=entry->name;
msg->rm_Args[2]=entry->comment;
msg->rm_Args[3]=(STRPTR)entry->protection;
/* Fill in the message correctly.
Arguments are integer/string/string/integer
1 0 0 1 = 9 */
if (!(FillRexxMsg(msg,4,9))) fail=1;
}
/* If we failed to create the message properly, release it and return */
if (fail) {
if (msg) DeleteRexxMsg(msg);
doerror(103);
return;
}
/* Forbid() to find the port */
Forbid();
if (!(port=FindPort(dir->custhandler))) {
char message[200];
/* Port was not out there; put up an error requester */
lsprintf(message,globstring[STR_CUSTPORT_NOT_FOUND],dir->custhandler);
simplerequest(message,str_okaystring,NULL);
/* Clear message and return */
ClearRexxMsg(msg,4);
DeleteRexxMsg(msg);
Permit();
return;
}
/* Turn busy pointer on and send the message */
busy();
PutMsg(port,(struct Message *)msg);
Permit();
SetSignal(0,INPUTSIG_ABORT);
FOREVER {
/* If abort sequence hit, break out immediately. The message is now
lost to us, we can never free it */
if ((Wait(1<<general_port->mp_SigBit|INPUTSIG_ABORT))&INPUTSIG_ABORT) {
status_haveaborted=status_justabort=0;
break;
}
/* If message has been replied, free it and break out */
if (reply=(struct RexxMsg *)GetMsg(general_port)) {
ClearRexxMsg(msg,4);
DeleteRexxMsg(msg);
break;
}
}
unbusy();
okay();
}
/* Opens the "special" dir in the window for a custom list */
void makespecialdir(win,title)
int win;
char *title;
{
freedir(dopus_specialwin[win],win);
if (dopus_curwin[win]!=dopus_specialwin[win]) {
dopus_oldwin[win]=dopus_curwin[win];
dopus_curwin[win]=dopus_specialwin[win];
}
strcpy(dopus_curwin[win]->diskname,title);
str_pathbuffer[win][0]=0;
checkdir(str_pathbuffer[win],&path_strgadget[win]);
freedir(dopus_curwin[win],win);
dopus_curwin[win]->diskfree=dopus_curwin[win]->disktot=dopus_curwin[win]->diskblock=-1;
}
/* Checks buffers to see if they need re-reading */
void check_old_buffer(win)
int win;
{
int reread=0;
if (config->dirflags&DIRFLAGS_REREADOLD && dopus_curwin[win]->directory[0]) {
if (dopus_curwin[win]->firstentry &&
(dopus_curwin[win]->firstentry->type==ENTRY_CUSTOM ||
dopus_curwin[win]->firstentry->type==ENTRY_DEVICE)) return;
else {
struct FileInfoBlock __aligned testinfo;
main_proc->pr_WindowPtr=(APTR)-1;
if (lockandexamine(dopus_curwin[win]->directory,&testinfo)) {
if (CompareDate(&dopus_curwin[win]->dirstamp,&testinfo.fib_Date)<0)
reread=1;
else if (!(config->dirflags&DIRFLAGS_EXPANDPATHS) &&
dopus_curwin[win]->volumename[0]) {
char rootname[256];
strcpy(rootname,dopus_curwin[win]->directory);
if (getroot(rootname,NULL) &&
(strcmp(rootname,dopus_curwin[win]->volumename))!=0)
reread=1;
}
}
if (config->errorflags&ERROR_ENABLE_DOS) main_proc->pr_WindowPtr=(APTR)Window;
}
if (reread) {
struct DirWindowPars notifypars;
notifypars.reselection_list=NULL;
makereselect(¬ifypars,win);
startgetdir(win,SGDFLAGS_REREADINGOLD);
doreselect(¬ifypars,0);
makereselect(¬ifypars,-1);
}
}
}
/* Refresh the display of a window */
void refreshwindow(win,type)
int win,type;
{
if (win>-1) {
if (dopus_curwin[win]->offset>dopus_curwin[win]->total-scrdata_dispwin_lines)
dopus_curwin[win]->offset=dopus_curwin[win]->total-scrdata_dispwin_lines;
if (dopus_curwin[win]->offset<0)
dopus_curwin[win]->offset=0;
if (type&1) {
fixprop(win);
fixhorizprop(win);
}
if (type&2) displayname(win,1);
dopus_curwin[win]->oldoff=dopus_curwin[win]->oldhoff=-1;
displaydir(win);
}
}
/* Move to a buffer */
void go_to_buffer(win,dir)
int win;
struct DirectoryWindow *dir;
{
endnotify(win);
dopus_curwin[win]=dir;
strcpy(str_pathbuffer[win],dir->directory);
checkdir(str_pathbuffer[win],&path_strgadget[win]);
checksize(win);
check_old_buffer(win);
refreshwindow(win,1);
doselinfo(win);
startnotify(win);
}